﻿<?php

define(LETTER_NUMBER, 256);

function char2Int( $c )
{
	$val = null;

	if (($c >= 'A') && ($c <= 'Z'))
		$val = ord($c) - ord('A');
	else
	{
		if (($c >= 'a') && ($c <= 'z'))
			$val = 26 + ord($c) - ord('a');
		else
		{
			if (($c >= '0') && ($c <= '9'))
				$val = 52 + ord($c) - ord('0');
			else
				if (($c >= '#') && ($c <= '$'))
					$val = 62 + ord($c) - ord('#');
		}
	}	
	return intval($val);
}

function int2Char( $val )
{
	$c = null;
	$val = intval($val);

	if (($val >= 0) && ($val <= 25))
		$c = ord('A') + $val ;
	else
	{
		if (($val >= 26) && ($val <= 51))
			$c = ord('a') + $val - 26;
		else
		{
			if (($val >= 52) && ($val <= 61))
				$c = ord('0') + $val - 52;
			else
				if (($val >= 62) && ($val <= 63))
					$c = ord('#') + $val - 62;
		}
	}
	return chr($c);
}

function generateCode($i, $p, $pp, $d) {
	$result = $p % ( 37 + $i );
	$result += $pp % ( 67 + 2 * $i );
	$result += $d % ( 131 + 3 * $i );
	return $result;
}

function getTodayDateTime()
{
	$round_numerator = 60 * 60 * 24;
	$rounded_time = ( round ( time() / $round_numerator ) * $round_numerator );
	return $rounded_time;
}

function subtemporalCrypt($data, $days, $ressourceid) {
	if( strlen( $data ) == 0 )
		return $data ;
			
	$days /= (60 * 60 * 24);
	$days = ceil($days);
	$pid = '' . $days;
	$pid = intval($pid[strlen($pid)-1]);
	
	$stringlength = 30 /*strlen($data)*/;
	$encodedlength = 8*$stringlength/6+2;

	$string_tab = array();
	
	for ($i = 0; $i < $stringlength; $i++)
	{
		$calc = ord(($i < strlen( $data ))? substr($data, $i, 1): '`');
	 	$calc += generateCode( $i+1, $pid, $ressourceid, $days );
		$calc %= LETTER_NUMBER;
	    $string_tab [$i] = $calc;
	}
	
	for ($i = 1; $i < $stringlength; $i++)
	{
	 	$calc = $string_tab [$i] + generateCode($string_tab [$i-1], $pid, $ressourceid, $days );
		$calc %= LETTER_NUMBER;
		$string_tab [$i] = $calc;
	}

	for ($i = $stringlength-2; $i >= 0; $i--)
	{
	 	$calc = $string_tab [$i] + generateCode($string_tab [$i+1], $pid, $ressourceid, $days );
		$calc %= LETTER_NUMBER;
		$string_tab [$i] = $calc;
	}

	for ($i = 1; $i < $stringlength; $i++)
	{
	 	$calc = $string_tab [$i] + generateCode($string_tab [$i-1], $pid, $ressourceid, $days );
		$calc %= LETTER_NUMBER;
		$string_tab [$i] = $calc;
	}

	for ($i = $stringlength-2; $i >= 0; $i--)
	{
	 	$calc = $string_tab [$i] + generateCode($string_tab [$i+1], $pid, $ressourceid, $days );
		$calc %= LETTER_NUMBER;
		$string_tab [$i] = $calc;
	}
	
	$i = $stringlength;

	while ( ($i%3) != 0)
	{
		$string_tab [$i] = (generateCode( $i, $pid, $ressourceid, $days ))%LETTER_NUMBER;
		$i++;
	}

	$db_tab = array();
	
	for ($i = 0; $i*3 < $stringlength; $i++)
	{
		$db_tab [$i*4  ] = (($string_tab [$i*3  ] & 0xfc) >> 2);
		$db_tab [$i*4+1] = (($string_tab [$i*3  ] & 0x03) << 4) + (($string_tab [$i*3+1] & 0xf0) >> 4);
		$db_tab [$i*4+2] = (($string_tab [$i*3+1] & 0x0f) << 2) + (($string_tab [$i*3+2] & 0xc0) >> 6);
		$db_tab [$i*4+3] = (($string_tab [$i*3+2] & 0x3f)     );
	}

	$ret_buffer = '';

	for ($i = 0; $i < $encodedlength-2; $i++)
		$ret_buffer .= int2Char ($db_tab [$i]);

	return $ret_buffer;	
}

function subtemporalDecrypt($initialdata, $days, $ressourceid) {
	if( strlen( $initialdata ) == 0 )
		return $initialdata ;
	
	$data = ' ' . $initialdata . ' ';		
	$initialdays = $days;
		
	$days /= (60 * 60 * 24);
	$days = ceil($days);
	$pid = '' . $days;
	$pid = intval($pid[strlen($pid)-1]);

	$stringlength = 30 /*strlen($data)*/;
	$encodedlength = 8*$stringlength/6+2;
	
	$db_tab = array();
	for ($i = 1; $i < $encodedlength-1; $i++)
		$db_tab [$i - 1] = char2Int (substr($data, $i, 1));
		
	$string_tab = array();
	for ($i = 0; $i*4 < $encodedlength-2; $i++)
	{
		$string_tab [$i*3  ] = (($db_tab [$i*4  ] & 0x3f) << 2) + (($db_tab [$i*4+1] & 0x30) >> 4);
		$string_tab [$i*3+1] = (($db_tab [$i*4+1] & 0x0f) << 4) + (($db_tab [$i*4+2] & 0x3c) >> 2);
		$string_tab [$i*3+2] = (($db_tab [$i*4+2] & 0x03) << 6) + (($db_tab [$i*4+3] & 0x3f)     );
	}
	
	for ($i = 0; $i <$stringlength-1; $i++)
	{
		$calc = $string_tab [$i] - generateCode( $string_tab [$i+1], $pid, $ressourceid, $days );
		while( $calc < 0 )
			$calc += LETTER_NUMBER;
		$string_tab [$i] = ($calc % LETTER_NUMBER);
	}
	
	for ($i = $stringlength-1; $i > 0; --$i)
	{
		$calc = $string_tab [$i] - generateCode( $string_tab [$i-1], $pid, $ressourceid, $days );
		while( $calc < 0 )
			$calc += LETTER_NUMBER;
		$string_tab [$i] = ($calc % LETTER_NUMBER);
	}
	
	for ($i = 0; $i <$stringlength-1; $i++)
	{
		$calc = $string_tab [$i] - generateCode( $string_tab [$i+1], $pid, $ressourceid, $days );
		while( $calc < 0 )
			$calc += LETTER_NUMBER;
		$string_tab [$i] = ($calc % LETTER_NUMBER);
	}
	
	for ($i = $stringlength-1; $i > 0; --$i)
	{
		$calc = $string_tab [$i] - generateCode( $string_tab [$i-1], $pid, $ressourceid, $days );
		while( $calc < 0 )
			$calc += LETTER_NUMBER;
		$string_tab [$i] = ($calc % LETTER_NUMBER);
	}
	

	$ret_buffer = '';
	for ($i = 0; $i < $stringlength; $i++)
	{
		$calc = $string_tab[$i] - generateCode( $i+1, $pid, $ressourceid, $days );
		
		while( $calc < 0 )
			$calc += LETTER_NUMBER;
		
		$letter = chr($calc % LETTER_NUMBER);
		if($letter != '`')
			$ret_buffer .= $letter;
		else
			break;
	}

	$recryptedData = subtemporalCrypt($ret_buffer, $initialdays, $ressourceid);

	if ($initialdata !== $recryptedData)
		throw new Exception("Cannot decrypt this data");

	return $ret_buffer;
}

function temporalCrypt($data, $days = null, $ressourceid = 2146) {
	$string = '';
	$result = '';
	$count = 0;
	if(!isset($days))
		$days = getTodayDateTime();
		
	for($i = 0; $i < strlen($data); $i++) {
		if(strlen($string) < 30)
			$string .= substr($data, $i, 1);
		else {
			$result .= subtemporalCrypt($string, $days + $count, $ressourceid + $count);
			$string = substr($data, $i, 1);
			$count++;
		}
	}
	if(strlen($string) > 0)
		$result .= subtemporalCrypt($string, $days + $count, $ressourceid  + $count);
		
	return $result;
}

function temporalDecrypt($data, $days = null, $ressourceid = 2146) {
	$string = '';
	$result = '';
	$count = 0;
	if(!isset($days))
		$days = getTodayDateTime();
		
	for($i = 0; $i < strlen($data); $i++) {
		if(strlen($string) < 40)
			$string .= substr($data, $i, 1);
		else {
			$result .= subtemporalDecrypt($string, $days  + $count, $ressourceid  + $count);
			$string = substr($data, $i, 1);
			$count++;
		}
	}
	if(strlen($string) > 0)
		$result .= subtemporalDecrypt($string, $days + $count, $ressourceid + $count );

	return $result;
}

$data = 'test';
$crypteddata = temporalCrypt($data);
$decrypteddata = temporalDecrypt($crypteddata);
echo "<br/>data[$data] -> [$decrypteddata]";

?>